package com.nightpiter.model;

import android.os.Handler;

import com.nightpiter.controller.MetroController;
import com.nightpiter.controller.log.Logger;

/**
 * MetroModelState class. Contains info about the current state of the Model
 * 
 * @author Eldar Abusalimov (eldar.abusalimov@gmail.com)
 */
public class MetroModelState implements Cloneable {
	/**
	 * Possible actions
	 * 
	 * @author Eldar Abusalimov (eldar.abusalimov@gmail.com)
	 */
	public enum Action {
		IDLE, READING, BUILDING, LOADING
	}

	/**
	 * Elements to process
	 * 
	 * @author Eldar Abusalimov (eldar.abusalimov@gmail.com)
	 */
	public enum Element {
		STATIONS, TUNNELS, TRANSFERS, HUBS, LINES, MAP, NONE;
	}

	/**
	 * the current action
	 */
	Action action = Action.IDLE;

	/**
	 * the current action
	 */
	Element element = Element.NONE;

	/**
	 * handler that would receive messages
	 */
	private Handler handler;

	/**
	 * true if the Model has already built
	 */
	boolean readyProgress = true;

	/**
	 * xml parsing progress
	 */
	boolean stationsReadProgress = true, tunnelsReadProgress = true,
			transfersReadProgress = true, linesReadProgress = true,
			readProgress = true;

	/**
	 * model building progress
	 */
	boolean hubsBuiltProgress = true, tunnelsBuiltProgress = true,
			transfersBuiltProgress = true, builtProgress = true;

	/**
	 * public constructor
	 */
	public MetroModelState() {
	}

	/**
	 * post a message about state change to the handler
	 */
	void notifyHandler() {
		if (this.handler != null) {
			MetroModelState state;
			try {
				state = (MetroModelState) this.clone();
			} catch (CloneNotSupportedException e) {
				state = this;
			}
			this.handler.sendMessage(this.handler.obtainMessage(
					MetroController.MSG_MODEL_STATE_CHANGED, state));
		} else {
			Logger.log("ERROR!!! Handler is not assigned!");
		}
	}

	/**
	 * set all progress field to false;
	 */
	void resetAll(Handler handler) {
		this.handler = handler;
		readyProgress = false;
		stationsReadProgress = tunnelsReadProgress = transfersReadProgress = linesReadProgress = readProgress = false;
		hubsBuiltProgress = tunnelsBuiltProgress = transfersBuiltProgress = builtProgress = false;
		notifyHandler();
	}

	/**
	 * @return the action
	 */
	public Action getAction() {
		return action;
	}

	/**
	 * @return the element
	 */
	public Element getElement() {
		return element;
	}

	/**
	 * @param readyProgress
	 *            the readyProgress to set
	 */
	void setReady(boolean readyProgress) {
		this.readyProgress = readyProgress;
		notifyHandler();
	}

	/**
	 * @param stationsReadProgress
	 *            the stationsReadProgress to set
	 */
	void setStationsRead(boolean stationsReadProgress) {
		this.stationsReadProgress = stationsReadProgress;
		// notifyHandler();
	}

	/**
	 * @param tunnelsReadProgress
	 *            the tunnelsReadProgress to set
	 */
	void setTunnelsRead(boolean tunnelsReadProgress) {
		this.tunnelsReadProgress = tunnelsReadProgress;
		// notifyHandler();
	}

	/**
	 * @param transfersReadProgress
	 *            the transfersReadProgress to set
	 */
	void setTransfersRead(boolean transfersReadProgress) {
		this.transfersReadProgress = transfersReadProgress;
		// notifyHandler();
	}

	/**
	 * @param linesReadProgress
	 *            the linesReadProgress to set
	 */
	void setLinesRead(boolean linesReadProgress) {
		this.linesReadProgress = linesReadProgress;
		// notifyHandler();
	}

	/**
	 * @param readProgress
	 *            the readProgress to set
	 */
	void setRead(boolean readProgress) {
		this.stationsReadProgress = readProgress;
		this.tunnelsReadProgress = readProgress;
		this.transfersReadProgress = readProgress;
		this.linesReadProgress = readProgress;
		this.readProgress = readProgress;
		notifyHandler();
	}

	/**
	 * @param tunnelsBuiltProgress
	 *            the tunnelsBuiltProgress to set
	 */
	void setTunnelsBuilt(boolean tunnelsBuiltProgress) {
		this.tunnelsBuiltProgress = tunnelsBuiltProgress;
		// notifyHandler();
	}

	/**
	 * @param transfersBuiltProgress
	 *            the transfersBuiltProgress to set
	 */
	void setTransfersBuilt(boolean transfersBuiltProgress) {
		this.transfersBuiltProgress = transfersBuiltProgress;
		// notifyHandler();
	}

	/**
	 * @param hubsBuiltProgress
	 *            the hubsBuiltProgress to set
	 */
	void setHubsBuilt(boolean hubsBuiltProgress) {
		this.hubsBuiltProgress = hubsBuiltProgress;
		// notifyHandler();
	}

	/**
	 * @param builtProgress
	 *            the builtProgress to set
	 */
	void setBuilt(boolean builtProgress) {
		this.tunnelsBuiltProgress = builtProgress;
		this.transfersBuiltProgress = builtProgress;
		this.hubsBuiltProgress = builtProgress;
		this.builtProgress = builtProgress;
		notifyHandler();
	}

	/**
	 * @return the readyProgress
	 */
	public boolean isReady() {
		return readyProgress;
	}

	/**
	 * @return the stationsReadProgress
	 */
	public boolean isStationsRead() {
		return stationsReadProgress;
	}

	/**
	 * @return the tunnelsReadProgress
	 */
	public boolean isTunnelsRead() {
		return tunnelsReadProgress;
	}

	/**
	 * @return the transfersReadProgress
	 */
	public boolean isTransfersRead() {
		return transfersReadProgress;
	}

	/**
	 * @return the linesReadProgress
	 */
	public boolean isLinesRead() {
		return linesReadProgress;
	}

	/**
	 * @return the readProgress
	 */
	public boolean isRead() {
		return readProgress;
	}

	/**
	 * @return the tunnelsBuiltProgress
	 */
	public boolean isTunnelsBuilt() {
		return tunnelsBuiltProgress;
	}

	/**
	 * @return the transfersBuiltProgress
	 */
	public boolean isTransfersBuilt() {
		return transfersBuiltProgress;
	}

	/**
	 * @return the hubsBuiltProgress
	 */
	public boolean isHubsBuilt() {
		return hubsBuiltProgress;
	}

	/**
	 * @return the builtProgress
	 */
	public boolean isBuilt() {
		return builtProgress;
	}

}
